package com.soyotec.algorithm.indicator;

import cn.hutool.core.io.file.FileReader;
import com.soyotec.algorithm.context.OptAlgorithmContext;
import com.soyotec.algorithm.context.OptAlgorithmLogContext;
import com.soyotec.algorithm.solution.ValueWrapSolution;
import com.soyotec.algorithm.util.MatUtil;

import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.Map;

/**
 * 通用的指标
 * @param <S> 解决方案
 */
public abstract class GenericIndicatorPlugin<S> implements QualityIndicatorPlugin<List<S>,Double> {
    /**
     * 标准Pareto解集
     */
    protected double[][] referenceParetoFront = null;

    protected OptAlgorithmContext optAlgorithmContext;

    public GenericIndicatorPlugin(){}

    public GenericIndicatorPlugin(String filePath){
        setReferenceParetoFront(filePath);
    }

    public GenericIndicatorPlugin(double[][] referenceParetoArray){
        setReferenceParetoFront(referenceParetoArray);
    }

    public void setReferenceParetoFront(String filePath){
        if(!isText(filePath)){
            //matfangfa
            Map<String,double[][]> matResult = MatUtil.readMatFile(filePath);
            this.referenceParetoFront = matResult.get("PF");
        } else {
            //txtFile

            if(filePath == null || "".equals(filePath)){
                if(optAlgorithmContext instanceof OptAlgorithmLogContext){
                    ((OptAlgorithmLogContext) optAlgorithmContext).writeLog("标准解集文件路径为空","The reference PSPF data file does not exist");
                }
                throw new RuntimeException("标准解集文件路径为空");
            }
            File file = new File(filePath);
            if(!file.exists()){
                if(optAlgorithmContext instanceof OptAlgorithmLogContext){
                    ((OptAlgorithmLogContext) optAlgorithmContext).writeLog("标准解集文件不存在","The reference PSPF data file does not exist");
                }
                throw new RuntimeException("标准解集文件不存在");
            }
            FileReader fileReader = new FileReader(file);
            List<String> lines = fileReader.readLines();
            this.referenceParetoFront = new double[lines.size()][];
            Integer beforeColumn = null;
            Integer nowColumn = null;
            for(int i = 0;i < lines.size();i++){
                String line = lines.get(i);
                String[] columnArray = line.split("\\s+");
                if(i == 0){
                    beforeColumn = columnArray.length;
                }
                nowColumn = columnArray.length;
                if(nowColumn != beforeColumn){
                    if(optAlgorithmContext instanceof OptAlgorithmLogContext){
                        ((OptAlgorithmLogContext) optAlgorithmContext).writeLog("标准解集文件不合法","The reference PSPF data file does not exist");
                    }
                    throw new RuntimeException("标准解集文件不合法");
                }
                for(int j = 0;j < columnArray.length;j++){
                    try {
                        referenceParetoFront[i][j] = Double.valueOf(columnArray[j]);
                    } catch (Exception e){
                        if(optAlgorithmContext instanceof OptAlgorithmLogContext){
                            ((OptAlgorithmLogContext) optAlgorithmContext).writeLog("标准解集文件不合法","The reference PSPF data file does not exist");
                        }
                        throw new RuntimeException("标准解集文件不合法");
                    }
                }
            }
        }

    }

    public void setReferenceParetoFront(double[][] referenceParetoArray){
        this.referenceParetoFront = referenceParetoArray;
    }

    public double[][] solutionToArray(List<? extends ValueWrapSolution> solutionList){
        if(solutionList == null || solutionList.isEmpty()){
            if(optAlgorithmContext instanceof OptAlgorithmLogContext){
                ((OptAlgorithmLogContext) optAlgorithmContext).writeLog("解集为空","The reference pareto set is empty");
            }
            throw new RuntimeException("解集为空");
        }

        double[][] result = new double[solutionList.size()][];
        for(int i = 0;i < solutionList.size();i++){
            ValueWrapSolution solution = solutionList.get(i);
            int numberOfObjectives = solution.getNumberOfObjectives();
            if(numberOfObjectives < 2){
                if(optAlgorithmContext instanceof OptAlgorithmLogContext){
                    ((OptAlgorithmLogContext) optAlgorithmContext).writeLog("解集目标个数不合法","Illegal number of objectives in reference PSPF data");
                }
                throw new RuntimeException("解集目标个数不合法");
            }
            result[i] = new double[numberOfObjectives];
            for(int j = 0;j < numberOfObjectives;j++){
                result[i][j] = solution.getObjective(j).getValue().getDoubleValue().doubleValue();
            }
        }
        return result;
    }


    /**
     * 判断文件是否为文本格式的文件
     *
     * @param filePath
     * @return
     */
    private static boolean isText(String filePath) {
        File file =new File(filePath);
        boolean isText = true;
        try {
            FileInputStream fin = new FileInputStream(file);
            long len = file.length();
            for (int j = 0; j < (int) len; j++) {
                int t = fin.read();
                if (t < 32 && t != 9 && t != 10 && t != 13) {
                    isText = false;
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return isText;
    }

}
